#!-*-coding: utf-8 -*-
"""
客户端
"""
from socket import *
from messageutil import *
import pickle, threading, struct
from clientprotocol import *

_host = "localhost"
_port = 18888
_stdout_mutex = threading.Lock()


class Client:
    def __init__(self, port = _port, host = _host):
        self.__host = _host
        self.__port = _port
        self.__init_client()
        # 添加粘包处理, 在消息前添加消息包的长度
        self.__msg_head_len = MESSAGE_HEAD_LENGTH
        # 主线程用于接收数据, 另开一个线程用于输入数据
        self.__input_thread = threading.Thread(target = self.__start_input, args = ())
        self.is_stoped = False  # 控制整个程序的运行状态，置为True后，结束发送数据和接收数据
        # 利用ClientProtocol类来处理客户端发送数据和接收来自服务器的数据
        self.__client_protocol = ClientProtocol()

    def __init_client(self):
        """
        desc:	初始化客户端socket
        param: 	空
        return:	空
        """
        self.__sock = socket(AF_INET, SOCK_STREAM)
        self.__sock.connect((self.__host, self.__port))

    def __del__(self):
        self.is_stoped = True
        self.__input_thread.join()
        self.__sock.close()

    def start(self):
        """
        desc:	启动客户端接收数据和发送数据
        param: 	空
        return:	空
        """
        self.__input_thread.start()	# 启动发送服务器请求的线程，以输入命令为驱动
        self.__start_recv()	# 主线程开始接收服务器返回的数据

    def __send(self, data):
        """
		desc:	客户端发送数据的接口
		param:
			data:	待发送的数据
		return:	空
		"""
        try:
            # 解析发送的数据，根据其输入的命令解析获取对应的发送消息
            msg = self.__client_protocol.parse_snd(data)
            #将待发送的消息进行封装，包括添加消息头，将消息序列化
            snd_msg = pack_msg(msg)
            #使用sock发送封装后的消息
            self.__sock.send(snd_msg)
        except Exception as ex:
            print(ex.message)

    def __start_input(self):
        """
        desc:	获取输入的命令，并通过发送接口发送封装后的命令数据
        param:	空
        return:	空
        """
        while True:
            input_data = raw_input()
            if str(input_data) == "exit":
                self.is_stoped = True
            if self.is_stoped:
                break
            self.__send(input_data)

    def __start_recv(self):
        """
        desc:	接收服务器的数据
        param:	空
        return:	空
        """
        while not self.is_stoped:
            msg_head = None
            try:
                # 接收消息头部，对应消息体的长度
                msg_head = self.__recv_data(self.__msg_head_len)
            # 服务器非正常关闭
            except:
                self.__deal_server_link_error()
                self.__sock.close()
                break
            # 服务器正常关闭
            if msg_head == -1:
                self.__deal_server_link_error()
                self.__sock.close()
                break
            else:
                msg_body_len = parse_head(msg_head)	# 解析消息体的长度
                #  接收消息体，并反序列化获取消息内容
                msg_body = self.__recv_data(msg_body_len)
                msg = parse_body(msg_body)
                #print(msg)
                self.__client_protocol.parse_recv(msg)

    def __deal_server_link_error(self):
        """
        desc:	处理服务器连接失败的错误
        param:	空
        return:	空
        """
        print("服务器连接中断!".decode("utf-8"))
        self.is_stoped = True

    def __recv_data(self, recv_len):
        """
        desc:	接收服务器发送的指定长度的数据
        param:
            recv_len:	接收数据的长度
        return:
            recv_data:	指定长度的来自于服务器的数据
        """
        recv_data = ""
        recv_data_len = 0
        while recv_data_len < recv_len:
            remain_len = recv_len - recv_data_len
            tmp_recv_data = self.__sock.recv(remain_len)
            if not tmp_recv_data:
                return -1
            recv_data += tmp_recv_data
            recv_data_len += len(tmp_recv_data)

        return recv_data

if __name__ == "__main__":
    client = Client()
    client.start()